package com.xyz.shiro;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.function.Function;


public abstract class BasicAuthorizingRealm extends AuthorizingRealm {


    public abstract Function<PrincipalCollection,AuthorizationInfo> getAuthorizationFunc();

    public abstract Function<AuthenticationToken,AuthenticationInfo> getAuthenticationFunc();

    public abstract Function<AuthenticationToken,Boolean> getSupports();

    private static final AllowAllCredentialsMatcher ALLOW_ALL = new AllowAllCredentialsMatcher();

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Function<PrincipalCollection,AuthorizationInfo> func = getAuthorizationFunc();
        if(func == null){
            func = (x)->{
                return new SimpleAuthorizationInfo();
            };
        }
        return func.apply(principalCollection);
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        Function<AuthenticationToken,AuthenticationInfo> func = getAuthenticationFunc();
        if(func == null){
            func = (x)->{
                return new SimpleAuthenticationInfo();
            };
        }
        return func.apply(authenticationToken);
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        Function<AuthenticationToken,Boolean> setting = getSupports();
        if(setting == null){
            return super.supports(token);
        }
        return setting.apply(token);
    }

    /**
     * 认证情报匹配用（目前不做检查）
     */
    @Override
    public final CredentialsMatcher getCredentialsMatcher()
    {
        // 在 getStoredPrincipal 的同时就进行所有的认证检查，所以这里就不需要做了
        return ALLOW_ALL;
    }

}
